#include "includes.h"
#include "spi.h"
#include "xrj_protocol_spi_mtd.h"
#include "w25qxx.h"
#include "xrj_mutex_lock.h"
/*函数定义*/

XRJ_IOT_MUTEX_S MtdSpi_Lock;

/*全局变量定义*/

 u16 number = 0;
/*局部变量定义*/


const u8 iCard_NoUSE[] = {	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
							0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
const u8 iCard_Null[] = {	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
							0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

void XRJ_MTD_SPI_Lock(void)
{	
	XRJ_mutex_lock(&MtdSpi_Lock);						
}

void XRJ_MTD_SPI_UnLock(void)
{	
	XRJ_mutex_unlock(&MtdSpi_Lock);						
}

static uint8_t CRC_CHECK(uint8_t * from,uint16_t size)
{
uint8_t  ret = 0x00 ;
uint16_t  i;	
		for(i = 0; i < size; i++)
		{
				ret ^= from[i];
		}	
		return ret;
}


UINT32 	MTD_SPI_Mapping_MAXBlock(UINT32 AddrMtd_Start)
{
UINT32 	MAXBlock = 0;
	switch(AddrMtd_Start)
	{
		case MTD_Block_Start_Factory:
			MAXBlock = 	MTD_Block_Num_Factory;
			break;
		case MTD_Block_Start_IDCard:
			MAXBlock = 	MTD_Block_Num_IDCard;
			break;		
		case MTD_Block_Start_Password:
			MAXBlock = 	MTD_Block_Num_Password;
			break;		
		default:
			MAXBlock = 0;
			break;
	}		
	return MAXBlock;	
}	


/**
  * @brief  在flash中查找固定长度的内容
  * @param  AddrMtd_Start: 分区首地址
  * @param  buf: 查找的内容
  * @param  size: 查找的空间大小
  * @param  rom_addr: 所在的SPI空间位置
  * @retval CARD_NO_FIND ：未找到
			CARD_FIND：查到卡
			CARD_ROM_FULL：ROM空间已经满了
  */
uint8_t	 MTD_SPI_Search(UINT32 AddrMtd_Start,uint8_t *buf, uint16_t size, uint32_t *rom_addr)
{
	uint16_t i,j;
	uint32_t addr = Block_Size*AddrMtd_Start;
	uint32_t dataAddr = 0;
	uint32_t num =Block_DATA/size;
	uint32_t Block_Max = MTD_SPI_Mapping_MAXBlock(AddrMtd_Start);
	
	for(i = 0; i < Block_Max; i++)
	{
		IWDG_Feed();
		W25QXX_Read(W25QXX_BUFFER, addr, Block_Size); 
		dataAddr = 0;
		for(j=0;j< num;j++)
		{       
              if(memcmp(&W25QXX_BUFFER[dataAddr],iCard_NoUSE,size) == 0)
              {
					//----
					*rom_addr = (addr+dataAddr);	
					return CARD_NO_FIND;
              }
              if(memcmp(&W25QXX_BUFFER[dataAddr],buf,size)==0)
              {
					*rom_addr = (addr+dataAddr);
					return CARD_FIND;
              }                    
              dataAddr += size;                
		} 
		addr += 4096;
	}
	return CARD_ROM_FULL;

}


uint8_t	 MTD_SPI_Search_Lock(UINT32 AddrMtd_Start,uint8_t *buf, uint16_t size, uint32_t *rom_addr)
{
	uint8_t ret;
	XRJ_MTD_SPI_Lock();
	ret = 	MTD_SPI_Search(AddrMtd_Start,buf,size,rom_addr);
	XRJ_MTD_SPI_UnLock();
	return ret;
}





//删除卡号
uint8_t MTD_SPI_Delete(UINT32 AddrMtd_Start,uint8_t *buf, uint16_t size)
{
uint32_t addr;	
	if	(MTD_SPI_Search(AddrMtd_Start,buf, size, &addr) != CARD_FIND)
	{
		return 0;
	}		
    W25QXX_Write((u8 *)iCard_Null, addr, size);  
    W25QXX_Read(W25QXX_BUFFER,addr,size); 
    if(memcmp(W25QXX_BUFFER,iCard_Null,size)!=0)
    {
        return 1;
    }
    return 0;
}

uint8_t MTD_SPI_Delete_Lock(UINT32 AddrMtd_Start,uint8_t *buf, uint16_t size)
{
	uint8_t ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_Delete(AddrMtd_Start,buf,size);
	XRJ_MTD_SPI_UnLock();
	return ret;	
}	


/* 保存数据 */
uint8_t MTD_SPI_ADD(UINT32 AddrMtd_Start,uint8_t *buf, uint16_t size)
{
uint32_t addr;	
	if	(MTD_SPI_Search(AddrMtd_Start,buf, size, &addr) != CARD_NO_FIND)
	{
		return 0;
	}	
	if	(MTD_SPI_Search(AddrMtd_Start,(u8 *)iCard_Null, size, &addr) == CARD_ROM_FULL) 
	{
		return 1;
	}	
		
	W25QXX_Write(buf,addr,size);  
	W25QXX_Read(W25QXX_BUFFER,addr,size); 
	if(memcmp(W25QXX_BUFFER,buf,size) != 0)
	{
		return 1;
	}
	return 0;
}

uint8_t MTD_SPI_ADD_Lock(UINT32 AddrMtd_Start,uint8_t *buf, uint16_t size)
{
	uint8_t ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_ADD(AddrMtd_Start, buf, size);	
	XRJ_MTD_SPI_UnLock();
	return ret;	
}


uint16_t MTD_SPI_GET_Num(UINT32 AddrMtd_Start,uint16_t size)
{
	u16 i,j;
	UINT32 flagEnd = 0;
	u32 addr = Block_Size*AddrMtd_Start;
	u32 dataAddr = 0;
	u16 cardNumber = 0;
	uint32_t num =Block_DATA/size;
	uint32_t Block_Max = MTD_SPI_Mapping_MAXBlock(AddrMtd_Start);
	for(i=0;i<Block_Max;i++)
	{
		IWDG_Feed();
		W25QXX_Read(W25QXX_BUFFER,addr,Block_Size); 
	
		dataAddr = 0;
		flagEnd = 0x00;
		for(j=0;j<num;j++)
		{      
			if (memcmp(&W25QXX_BUFFER[dataAddr],iCard_NoUSE,size) != 0)
			{
				flagEnd =0xff;
				if(memcmp(&W25QXX_BUFFER[dataAddr],iCard_Null,size) != 0 )
				{
					cardNumber++;	
				}				
			}	
			else
			{
				flagEnd = 0;
				break;
			}	
			dataAddr += size;                     
		} 
		addr += 4096;
		//-----如果全部都为未使用，表示查到最后空间，
		if (flagEnd == 0x00)
			break;
	}  
	return cardNumber;
}

uint16_t MTD_SPI_GET_Num_Lock(UINT32 AddrMtd_Start,uint16_t size)
{
	uint16_t ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_GET_Num(AddrMtd_Start, size);
	XRJ_MTD_SPI_UnLock();
	return ret;
}

uint16_t MTD_SPI_Del_Groud(UINT32 AddrMtd_Start)
{
	u16 i;
	uint32_t Block_Max = MTD_SPI_Mapping_MAXBlock(AddrMtd_Start);
	for(i= 0;i < Block_Max;i++)
	{	//------起始块从1开始
		IWDG_Feed();
		W25QXX_Erase_Sector(AddrMtd_Start+i);		
	}  
	return 0;
}

uint16_t MTD_SPI_Del_Groud_Lock(UINT32 AddrMtd_Start)
{
	uint16_t ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_Del_Groud(AddrMtd_Start);
	XRJ_MTD_SPI_UnLock();
	return ret;
}



uint16_t MTD_SPI_Erase_Block(UINT32 AddrMtd_Start)
{
	UINT32 Block_Start = AddrMtd_Start*4096; 
	UINT32 i;
	UINT32 Block_Addr = Block_Start;	
	for (i= 0;i < 4;i++)
	{
		W25QXX_Erase_Block(Block_Addr);
		Block_Addr += 0x10000; 
	}	
	return 0;
}


uint16_t MTD_SPI_Erase_Block_Lock(UINT32 AddrMtd_Start)
{
	uint16_t ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_Erase_Block(AddrMtd_Start);
	XRJ_MTD_SPI_UnLock();
	return ret;
}




INT32 MTD_SPI_Set_Write(UINT32 AddrMtd_Start, UINT32 Offset, UINT8 *buf, UINT16 size)
{
UINT32	addr = AddrMtd_Start*4096+Offset;
	W25QXX_Write(buf,addr,size);  
	W25QXX_Read(W25QXX_BUFFER,addr,size); 
	if(memcmp(W25QXX_BUFFER,buf,size) != 0)
	{
		return 1;
	}
	return 0;
}

INT32 MTD_SPI_Set_Write_Lock(UINT32 AddrMtd_Start, UINT32 Offset, UINT8 *buf, UINT16 size)
{
	INT32 ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_Set_Write(AddrMtd_Start, Offset, buf, size);
	XRJ_MTD_SPI_UnLock();
	return ret;
}



INT32 MTD_SPI_Set_Read(UINT32 AddrMtd_Start, UINT32 Offset, UINT8 *buf, UINT16 size)
{
UINT32	addr = AddrMtd_Start*4096+Offset;
	W25QXX_Read(buf,addr,size);  
	return 0;
}

INT32 MTD_SPI_Set_Read_Lock(UINT32 AddrMtd_Start, UINT32 Offset, UINT8 *buf, UINT16 size)
{
	INT32 ret;
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_Set_Read(AddrMtd_Start, Offset, buf, size);
	XRJ_MTD_SPI_UnLock();
	return ret;
}



UINT8 MTD_SPI_GET_Check(UINT32 AddrMtd_Start, UINT32 Offset, UINT16 size)
{
UINT32	addr = AddrMtd_Start*4096+Offset;
UINT8 crc;
	W25QXX_Read(W25QXX_BUFFER, addr, size);  
	crc = CRC_CHECK(W25QXX_BUFFER,size);
	return crc;
}


UINT8 MTD_SPI_GET_Check_Lock(UINT32 AddrMtd_Start, UINT32 Offset, UINT16 size)
{
UINT8 ret; 	
	XRJ_MTD_SPI_Lock();
	ret = MTD_SPI_GET_Check(AddrMtd_Start, Offset, size);
	XRJ_MTD_SPI_UnLock();
	return ret;
}	


INT32 MTD_SPI_Set_Init(void)
{
			XRJ_mutex_init(&MtdSpi_Lock);
#if 0	
UINT8	buf[4];
//UINT8 FACT_TAB[3] = {1,2,1};
//	MTD_SPI_Set_Write(MTD_Block_Start_Factory, Set_UnlockWarnEn_Offset, &FACT_TAB[0], 1);
//	MTD_SPI_Set_Write(MTD_Block_Start_Factory, Set_LockTime_Offset, &FACT_TAB[1], 1);	
//	MTD_SPI_Set_Write(MTD_Block_Start_Factory, Set_SwitchMode_Offset, &FACT_TAB[2], 1);	
	

	
	MTD_SPI_Set_Read(MTD_Block_Start_Factory, Set_UnlockWarnEn_Offset, buf, 1);
	currentDataPoint.Value_Setting_UnlockWarnEnable = buf[0];
	currentDataPoint.Value_Setting_UnlockWarnEnable_Bak = buf[0];
	
	MTD_SPI_Set_Read(MTD_Block_Start_Factory, Set_TamperAlarmEn_Offset, buf, 1);
	currentDataPoint.Value_Setting_TamperAlarm_Enable = buf[0];
	currentDataPoint.Value_Setting_TamperAlarm_Enable_Bak = buf[0];	
	
	
	MTD_SPI_Set_Read(MTD_Block_Start_Factory, Set_LockTime_Offset, buf, 1);
	if (buf[0] > 20)
	{
		buf[0] = 20;
	}	
	currentDataPoint.Value_Setting_LockTime = buf[0];
	currentDataPoint.Value_Setting_LockTime_Bak = buf[0];
	
	MTD_SPI_Set_Read(MTD_Block_Start_Factory, Set_SwitchMode_Offset, buf, 1);	
	currentDataPoint.Value_Setting_SwitchMode = buf[0];
	currentDataPoint.Value_Setting_SwitchMode_Bak = buf[0];	

	
	Lock_Time_Set(currentDataPoint.Value_Setting_LockTime);	
	Lock_SwitchMode_Set(currentDataPoint.Value_Setting_SwitchMode);
	
	MTD_SPI_UUID_KEY();
//	MTD_SPI_Erase_Block(MTD_Block_Start_PrgInit);
	
#endif 	
	return 0;
}	
/*
 #define	UUID_Offset					1024
#define	UUID_Len					16
#define	PRODUCTKEY_Offset			(UUID_Offset+UUID_Len)
#define	PRODUCTKEY_Len				16
*/



INT32 MTD_SPI_UUID_KEY(void)
{
#if 0	
	INT32	i;
#if	0
	UINT8	uuidtest[16] = 	XRJ_DEVICE_NAME_TAB;
	char 	keytestb[] = XRJ_PRODUCT_KEY;
	char	buf[48];
	memset(buf,0,48);
	strcpy(buf,keytestb);
	MTD_SPI_Set_Write(MTD_Block_Start_Factory, UUID_Offset, uuidtest, 16);
	MTD_SPI_Set_Write(MTD_Block_Start_Factory, PRODUCTKEY_Offset, (UINT8 *)buf, 16);
#endif	
	memset((UINT8 *)(&XRJ_BOARD_INFO),0,sizeof(XRJ_BOARD_INFO));
	MTD_SPI_Set_Read(MTD_Block_Start_Factory, UUID_Offset, (UINT8 *)XRJ_BOARD_INFO.DEVICE_UUID_HEX, UUID_Len);	
	MTD_SPI_Set_Read(MTD_Block_Start_Factory, PRODUCTKEY_Offset, (UINT8 *)XRJ_BOARD_INFO.PRODUCT_KEY ,  PRODUCTKEY_Len);
	
	memset(XRJ_BOARD_INFO.DEVICE_UUID_STRING,0,48);
	for (i = 0; i < 16; i++)
	{
		sprintf(&XRJ_BOARD_INFO.DEVICE_UUID_STRING[i*2],"%02x",XRJ_BOARD_INFO.DEVICE_UUID_HEX[i]);
	}
	
	snprintf(XRJ_BOARD_INFO.TopicUpdate,96,"/%s/%s/update",XRJ_BOARD_INFO.PRODUCT_KEY,XRJ_BOARD_INFO.DEVICE_UUID_STRING);
	snprintf(XRJ_BOARD_INFO.TopicGet,96,"/%s/%s/get",XRJ_BOARD_INFO.PRODUCT_KEY,XRJ_BOARD_INFO.DEVICE_UUID_STRING);
#if	TYPE_URL == TYPE_Domain	
	strcpy(XRJ_BOARD_INFO.HOST_NAME,XRJ_HOST_NAME_Domain);
#else
	if (FLAG_Net_Type == Net_GSM)
	{	
		strcpy(XRJ_BOARD_INFO.HOST_NAME,XRJ_HOST_NAME_IPGSM);
	}
	else
	{
		strcpy(XRJ_BOARD_INFO.HOST_NAME,XRJ_HOST_NAME_IPWIFI);
	}	
#endif
#endif
	return 0;
}	

